package cn.com.libertymutual.wx;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mobile.device.Device;
import org.springframework.mobile.device.DeviceUtils;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import cn.com.libertymutual.core.annotation.SystemValidate;
import cn.com.libertymutual.core.util.Constants;
import cn.com.libertymutual.core.web.ServiceResult;
import cn.com.libertymutual.sp.bean.TbSpShare;
import cn.com.libertymutual.sp.bean.TbSpUser;
import cn.com.libertymutual.sp.biz.IdentifierMarkBiz;
import cn.com.libertymutual.sp.dao.KeywordWeChatDao;
import cn.com.libertymutual.sp.dao.ShareDao;
import cn.com.libertymutual.sp.dao.UserDao;
import cn.com.libertymutual.sp.dto.wechat.RuleReplyMsg;
import cn.com.libertymutual.sp.dto.wechat.TQueryRuleMsgResponseDto;
import cn.com.libertymutual.sp.service.api.QueryPrdCodeService;
import cn.com.libertymutual.sp.service.api.UserService;
import cn.com.libertymutual.wx.common.MessageType;
import cn.com.libertymutual.wx.common.ResponseMessageParser;
import cn.com.libertymutual.wx.message.UserToken;
import cn.com.libertymutual.wx.message.WeChatUser;
import cn.com.libertymutual.wx.message.responsedto.ResponseBaseMessage;
import cn.com.libertymutual.wx.message.responsedto.TextMessage;
import cn.com.libertymutual.wx.service.WeChatService;
import cn.com.libertymutual.wx.util.WXUtil;

@RestController
@RequestMapping(value = "/nol/wechat")
public class WXController {

	private Logger logger = LoggerFactory.getLogger(getClass());
	@Resource
	private ShareDao shareDao;
	@Resource
	private UserDao userDao;
	@Autowired
	private KeywordWeChatDao keywordWeChatDao;

	@Resource
	private UserService userService;
	@Resource
	private WeChatService weChatService;
	@Autowired
	private QueryPrdCodeService queryPrdCodeService;
	@Resource
	private IdentifierMarkBiz identifierMarkBiz;

	@Resource
	private WXUtil wxUtil;

	/**Remarks: 微信接口开发前签名<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年11月15日上午11:49:23<br>
	 * Project：liberty_sale_plat<br>
	 * @param signature
	 * @param timestamp
	 * @param nonce
	 * @param echostr
	 * @return
	 */
	@RequestMapping(value = "/verify", method = RequestMethod.GET)
	@SystemValidate(validate = false, description = "无需校验接口")
	public String verify(@RequestParam(name = "signature", required = false) String signature,
			@RequestParam(name = "timestamp", required = false) String timestamp, @RequestParam(name = "nonce", required = false) String nonce,
			@RequestParam(name = "echostr", required = false) String echostr) {
		logger.info("WeChat校验签名===>signature={},timestamp={},nonce={},echostr={}", signature, timestamp, nonce, echostr);
		// 排序
		String sortString = weChatService.sort(timestamp, nonce);
		// 加密
		String myString = weChatService.sha1(sortString);
		// 校验
		if (StringUtils.isNotBlank(myString) && myString.equals(signature)) {
			logger.info("签名校验通过===>{}", signature);
			// 如果检验成功原样返回echostr，微信服务器接收到此输出，才会确认检验完成。
			return echostr;
		} else {
			logger.info("签名校验失败===>myString={},signature={}", myString, signature);
			return "";
		}
	}

	/**Remarks: 接收消息并校验请求参数做相应处理<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年11月16日上午9:56:30<br>
	 * Project：liberty_sale_plat<br>
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "/verify", method = RequestMethod.POST)
	@SystemValidate(validate = false, description = "无需校验接口")
	public String verifyAndReceiveMessage(HttpServletRequest request, HttpServletResponse response) {
		String returnXML = "";
		try {
			// 设置微信输入的XML编码格式为 UTF-8
			request.setCharacterEncoding("UTF-8");
			// 获取输入流
			ServletInputStream in = request.getInputStream();

			// 把输入流转换为XML 字符串
			String inputXml = weChatService.inputStream2String(in);
			// String inputXml = "<xml><ToUserName><![CDATA[gh_19bdee1b51ef]]></ToUserName>"
			// + "<FromUserName><![CDATA[oGNKntzzB-GdPYY69BSGAkdmSzSc]]></FromUserName>" +
			// "<CreateTime>1523158613</CreateTime>"
			// + "<MsgType><![CDATA[text]]></MsgType>" +
			// "<Content><![CDATA[@sdf@]]></Content>" + "<MsgId>6541916429876258201</MsgId>"
			// + "</xml>";

			// 释放资源
			in.close();
			in = null;

			logger.info("微信请求XML===>{}", inputXml);

			// // 处理输入信息，并做出响应
			Map<String, String> receiveMap = weChatService.parseXml(inputXml);
			logger.info("微信请求转换的MAP===>{}", receiveMap);

			// 发送方帐号（open_id）
			String fromUserName = receiveMap.get("FromUserName");
			// 公众帐号
			String toUserName = receiveMap.get("ToUserName");
			// 消息类型
			String msgType = receiveMap.get("MsgType");

			// 回复消息统一参数
			ResponseBaseMessage outputMessage = new ResponseBaseMessage();
			outputMessage.setFromUserName(toUserName);// 发送方与接收方取反
			outputMessage.setToUserName(fromUserName);// 发送方与接收方取反
			TextMessage textMessage = new TextMessage(outputMessage);

			// 验车码事件处理
			if (MessageType.REQ_MESSAGE_TYPE_EVENT.equals(msgType)) {
				String event = receiveMap.get("Event");
				// 按钮事件
				if (MessageType.EVENT_TYPE_CLICK.equals(event)) {

					// 按钮的KEY
					String EventKey = receiveMap.get("EventKey");
					switch (EventKey) {
					case "SALE_PLAT_CAR_CODE":// 验车码按钮
						return queryPrdCodeService.executeQueryCheckCode(returnXML, textMessage);
					default:
						break;
					}
				}
			}

			// 默认回复
			// textMessage.setContent(wxUtil.getAUTORETURNMSG());
			textMessage.setContent(keywordWeChatDao.findAutoReturnMsg(Constants.KEY_WORDS_AUTORETURNMSG));

			// 关键词消息回复
			String content = receiveMap.get("Content");
			if (StringUtils.isNotBlank(content)) {
				Map<String, String> map = weChatService.keywordsReplyAndReturnXml(request, fromUserName, content, returnXML, textMessage);
				if (map.get("type").equals("msg")) {
					return "";
				}
				if (map.get("type").equals("xml") && map.get("state").equals("true")) {
					return map.get("xml");
				}
			}

			// 查询回复规则
			TQueryRuleMsgResponseDto msgResponseDto = weChatService.getRule(receiveMap);
			List<RuleReplyMsg> ruleReplyMsgs = msgResponseDto.getRuleReplyMsgs();

			// 查询规则失败，回复默认
			if (!msgResponseDto.getStatus()) {
				returnXML = ResponseMessageParser.textMessageToXml(textMessage);// 将回复内容转换成xml字符串
				return returnXML;
			}

			// 事件处理
			if (MessageType.REQ_MESSAGE_TYPE_EVENT.equals(msgType)) {

				String event = receiveMap.get("Event");

				if (MessageType.EVENT_TYPE_SUBSCRIBE.equals(event)) {

					returnXML = ResponseMessageParser.textMessageToXml(textMessage);

					List<TbSpUser> users = userDao.findByWxOpenId(fromUserName);
					if (CollectionUtils.isNotEmpty(users) && users.size() == 1) {

						TbSpUser user = users.get(0);
						user.setWxSubscribe("1");// 已关注
						userDao.save(user);// 更新微信信息
					}

					logger.info("微信用户[{}]正在关注", fromUserName);

				} else if (MessageType.EVENT_TYPE_SCAN.equals(event)) {

					returnXML = ResponseMessageParser.textMessageToXml(textMessage);

					List<TbSpUser> users = userDao.findByWxOpenId(fromUserName);
					if (CollectionUtils.isNotEmpty(users) && users.size() == 1) {
						TbSpUser user = users.get(0);
						user.setWxSubscribe("1");
						userDao.save(user);
					}

					logger.info("已关注的微信用户[{}]扫描二维码", fromUserName);

				} else if (MessageType.EVENT_TYPE_UNSUBSCRIBE.equals(event)) {
					List<TbSpUser> users = userDao.findByWxOpenId(fromUserName);
					if (CollectionUtils.isNotEmpty(users) && users.size() == 1) {
						TbSpUser user = users.get(0);
						user.setWxSubscribe("0");
						userDao.save(user);
					}
					// returnXML = ResponseMessageParser.textMessageToXml(textMessage);
					logger.info("微信用户[{}]已取消关注", fromUserName);

				} else {

					// returnXML = ResponseMessageParser.textMessageToXml(textMessage);
					logger.info("微信用户[{}]其他操作事件", fromUserName);

				}
			} else {

				// 查询到的回复规则条数为0则直接返回错误信息
				if (CollectionUtils.sizeIsEmpty(ruleReplyMsgs)) {

					RuleReplyMsg ruleReplyMsg = new RuleReplyMsg();
					if (StringUtils.isNotBlank(msgResponseDto.getResultMessage())) {
						// 有错误信息
						ruleReplyMsg.setContent(msgResponseDto.getResultMessage());
						ruleReplyMsg.setMsgType(MessageType.RESP_MESSAGE_TYPE_TEXT);
						// 回复单条信息
						return weChatService.returnSingleMsg(returnXML, receiveMap, outputMessage, textMessage, ruleReplyMsg);
					} else {
						return returnXML;
					}
				}

				logger.info("回复规则条数：{}", ruleReplyMsgs.size());

				// 临时选择第一个查看是否需要回复全部用户
				RuleReplyMsg ruleReplyMsg = ruleReplyMsgs.get(0);

				if (ruleReplyMsg.getRule() == null) {
					// 回复单条信息
					returnXML = weChatService.returnSingleMsg(returnXML, receiveMap, outputMessage, textMessage, ruleReplyMsg);
					return returnXML;
				}
				// 0=否，1=多条回复
				if (ruleReplyMsg.getRule().getIsReplyAll().compareTo(0) == 0) {

					// 回复单条信息
					returnXML = weChatService.returnSingleMsg(returnXML, receiveMap, outputMessage, textMessage, ruleReplyMsg);

				} else if (ruleReplyMsg.getRule().getIsReplyAll().compareTo(1) == 0) {
					// 循环所有回复规则，发送多条信息
					for (RuleReplyMsg replyMsg : ruleReplyMsgs) {

						JSONObject params = new JSONObject();
						// params.put("touser", fromUserName);
						// params.put("msgtype", replyMsg.getMsgType());

						if (MessageType.REQ_MESSAGE_TYPE_TEXT.equals(replyMsg.getMsgType())) {

							// params.put("text", new JSONObject().put("content", replyMsg.getContent()));

							params = JSONObject.parseObject(replyMsg.getContent());
							weChatService.sendMessage(params.toJSONString());

							logger.info("正在发送[文本]消息，到微信用户[{}]，{}", fromUserName, params.toJSONString());

						} else if (MessageType.REQ_MESSAGE_TYPE_IMAGE.equals(replyMsg.getMsgType())) {

							// params.put("image", new JSONObject().put("media_id",
							// receiveMap.get("MediaId")));

							params = JSONObject.parseObject(replyMsg.getContent());
							weChatService.sendMessage(params.toJSONString());

							logger.info("正在发送[图片]消息，到微信用户[{}]，{}", fromUserName, params.toJSONString());

						} else if (MessageType.REQ_MESSAGE_TYPE_LINK.equals(replyMsg.getMsgType())) {

							params = JSONObject.parseObject(replyMsg.getContent());
							weChatService.sendMessage(params.toJSONString());
							logger.info("正在发送[链接]消息，到微信用户[{}]，{}", fromUserName, params.toJSONString());

						} else if (MessageType.REQ_MESSAGE_TYPE_LOCATION.equals(replyMsg.getMsgType())) {

							params = JSONObject.parseObject(replyMsg.getContent());
							weChatService.sendMessage(params.toJSONString());
							logger.info("正在发送[地理位置]消息，到微信用户[{}]，{}", fromUserName, params.toJSONString());

						} else if (MessageType.RESP_MESSAGE_TYPE_MUSIC.equals(replyMsg.getMsgType())) {

							params = JSONObject.parseObject(replyMsg.getContent());
							weChatService.sendMessage(params.toJSONString());
							logger.info("正在发送[音乐]消息，到微信用户[{}]，{}", fromUserName, params.toJSONString());

						} else if (MessageType.REQ_MESSAGE_TYPE_VOICE.equals(replyMsg.getMsgType())) {

							// params.put("voice", new JSONObject().put("media_id",
							// receiveMap.get("MediaId")));

							params = JSONObject.parseObject(replyMsg.getContent());
							weChatService.sendMessage(params.toJSONString());

							logger.info("正在发送[语音]消息，到微信用户[{}]，{}", fromUserName, params.toJSONString());

						} else if (MessageType.REQ_MESSAGE_TYPE_VIDEO.equals(replyMsg.getMsgType())) {

							// params.put("video", new JSONObject().put("media_id",
							// receiveMap.get("MediaId")));
							// params.put("title", new JSONObject().put("title", "标题"));
							// params.put("video", new JSONObject().put("description", "描述~"));

							params = JSONObject.parseObject(replyMsg.getContent());
							weChatService.sendMessage(params.toJSONString());

							logger.info("正在发送[视频]消息，到微信用户[{}]，{}", fromUserName, params.toJSONString());

						} else {

							logger.info("正在发送[其他]消息，来自微信用户[{}]，{}", fromUserName, params.toJSONString());
						}
					}
					returnXML = ResponseMessageParser.textMessageToXml(textMessage);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		logger.info("回复消息XML===>returnXML={}", returnXML);
		return returnXML;
	}

	// 静默授权
	@RequestMapping(value = "/snsapi_base", method = RequestMethod.GET)
	public void silentOauth(@RequestAttribute(DeviceUtils.CURRENT_DEVICE_ATTRIBUTE) Device device,
			@RequestParam(name = "url", required = false) String url, @RequestParam(name = "code", required = false) String code,
			@RequestParam(name = "state", required = false) String state, HttpServletRequest req, HttpServletResponse resp) {
		this.getRedirect(device, req, resp, url, state, code, WXUtil.SNSAPI_BASE);
	}

	// 网页授权
	@RequestMapping(value = "/snsapi_userinfo", method = RequestMethod.GET)
	@SystemValidate(validate = false, description = "无需校验接口")
	public void oauth(@RequestAttribute(DeviceUtils.CURRENT_DEVICE_ATTRIBUTE) Device device, @RequestParam(name = "url", required = false) String url,
			@RequestParam(name = "code", required = false) String code, @RequestParam(name = "state", required = false) String state,
			HttpServletRequest req, HttpServletResponse resp) {
		this.getRedirect(device, req, resp, url, state, code, WXUtil.SNSAPI_USERINFO);
	}

	/**Remarks: 获取根据微信返回的code获取token再获取用户信息再重定向页面<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年10月22日下午10:46:41<br>
	 * Project：liberty_sale_plat<br>
	 * @param req
	 * @param resp
	 * @param url
	 * @param state
	 * @param code
	 * @param mode
	 * @param userCode
	 */
	private void getRedirect(Device device, HttpServletRequest request, HttpServletResponse response, String url, String state, String code,
			String mode) {
		ServiceResult sr = new ServiceResult(Constants.SYS_ERROR_MSG, ServiceResult.STATE_EXCEPTION);
		try {
			logger.info("微信授权回调，全部参数：===url==>{}===state==>{}===code==>{}===mode==>{}", url, state, code, mode);

			String shareId = "henghua";// 分享 参数
			String oathType = "default";// 授权类型或者用户code
			if (StringUtils.isNotBlank(state)) {
				shareId = state.split(",")[0];// 分享 参数
				if (state.indexOf(",") > 0) {
					oathType = state.split(",")[1];// 授权类型或者用户code
				}
			}

			// code若被使用之后,原来的access_token5分钟内会销毁
			if (StringUtils.isBlank(code)) {
				response.sendRedirect(url);
				return;
			}
			// 每次获取新的access_token,官方无次数限制
			UserToken userToken = weChatService.getUserAccessToken(code);
			if (null == userToken) {
				response.sendRedirect(url);
				return;
			}
			// 获取微信用户基本信息
			WeChatUser weChatUser = weChatService.getUserInfo(userToken.getAccessToken(), userToken.getOpenId(), mode);
			// 静默授权方可获取是否关注的状态
			weChatUser = weChatService.getUserInfo(weChatService.getPublicAccessTokenCurrent("静默授权"), userToken.getOpenId(), WXUtil.SNSAPI_BASE);
			if (null == weChatUser) {
				response.sendRedirect(url);
				return;
			}

			List<TbSpShare> spShare = shareDao.findByShareId(shareId);
			String superUserCode = "";
			if (CollectionUtils.isNotEmpty(spShare) && spShare.size() > 0) {
				superUserCode = spShare.get(0).getUserCode();
			}
			logger.info("**************分享人的superUserCode***************>{}", superUserCode);

			if (StringUtils.isNotBlank(oathType) && oathType.toUpperCase().startsWith("BS")) {// 渠道授权注册
				// 微信用户入库保存到刚提交的普通账户
				sr = userService.saveWeChatToBsUser(sr, weChatUser, superUserCode, oathType);
			} else {
				sr = userService.updateUserByOpenId(request, sr, weChatUser, userToken.getOpenId());
				// 已授权
				if (ServiceResult.STATE_SUCCESS == sr.getState()) {

					identifierMarkBiz.setHeadersToken(device, response, sr);// 根据用户信息设置token

					logger.info("serviceResult已授权==>{}", JSON.toJSONString(sr));
					if (url.indexOf("?") > 0) {
						response.sendRedirect(url + "&openid=" + userToken.getOpenId());
					} else {
						response.sendRedirect(url + "?openid=" + userToken.getOpenId());
					}
					return;
				}
				// 微信用户入库保存
				sr = userService.saveWeChatUser(sr, weChatUser, superUserCode, null);
			}
			identifierMarkBiz.setHeadersToken(device, response, sr);// 根据用户信息设置token

			logger.info("serviceResult入库==>{}", JSON.toJSONString(sr));

			String goUrl = url;
			if (url.indexOf("?") > 0) {
				goUrl += "&openid=" + userToken.getOpenId();
			} else {
				goUrl += "?openid=" + userToken.getOpenId();
			}
			logger.info("============授权成功，开始跳转==>{}", goUrl);

			response.sendRedirect(goUrl);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**Remarks: 获取微信分享需要的JSTicket<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年10月29日下午12:56:44<br>
	 * Project：liberty_sale_plat<br>
	 * @return
	 */
	@RequestMapping(value = "/ticket", method = RequestMethod.GET)
	@SystemValidate(validate = false, description = "无需校验接口")
	public String getTicket() {
		return weChatService.getJSTicket();
	}
}
